# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.

from os import path

dir = path.dirname(path.realpath(__file__))
path = dir + '/test_' + path.basename(dir) + '_{}.cj'

template = '''
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

/*
  @Assertion:   16.2(9) 7.Arithmetic, relational, bitwise expressions of the numeric types, Bool, Unit, Rune, String
                types, all operands must be const expressions.
  @Description: %s
  @Mode: %s
  @Negative: %s
  @Structure: single
  @CompileWarning: no
  @Comment: Auto-generated by gen.py
  @Issue: 6614
*/
%s
main() {
    %s
    return 0
}
'''

type_info = {
  'i': ('Int64', 1),
  'c': ('Rune', "'1'"),
  's': ('String', '"1"'),
  'f': ('Float64', '1.0'),
  'u': ('Unit', '()'),
  'b': ('Bool', 'true')
}

op_info = [
  ('-', 'neg', -1, {'arity' : 1}),
  ('+', 'add', 2),
  ('-', 'sub', 0),
  ('*', 'mul', 1),
  ('/', 'div', 1),
  ('%', 'rem', 0),
  ('<<', 'shl', 2),
  ('>>', 'shr', 0),
  ('^', 'xor', 0),
  ('&', 'band', 1),
  ('|', 'bor', 1),
  ('>', 'gt', 'false'),
  ('<', 'lt', 'false'),
  ('>=', 'geq', 'true'),
  ('<=', 'leq', 'true'),
  ('!', 'inv', 'false', {'arity' : 1, 'type' : 'b'}),
  ('&&', 'land', 'true', {'type' : 'b'}),
  ('||', 'lor', 'true', {'type' : 'b'}),
  ('**', 'pow', '1.0', {'type' : 'f'}),
  ('+', 'concat', '"11"', {'type' : 's'}),
  *[('==', t + 'eq', 'true', {'type' : t}) for t in type_info],
  *[('!=', t + 'neq', 'false', {'type' : t}) for t in type_info],
]

def get_params(info):
  params = {
    'type': 'i',
    'arity': 2
  }
  if (len(info) > 3): params.update(info[3])
  return params

def rhs_expr(a, op, b, arity):
  return f'{a} {op} {b}' if arity == 2 else f'{op}{a}'

def expr(info, params):
  ty = params['type']
  rhs = rhs_expr(ty + '()', info[0], type_info[ty][1], params['arity'])
  return f'const {info[1]} = {rhs}'

def case(info, params):
  return f'''{expr(info, params)}
    Assert.equals({info[2]}, {info[1]})'''

positive_test = template % ('''Check that arithmetic, relational, bitwise expressions of the numeric types, Bool, Unit, Rune, String
                types, where all operands are const expressions, are const.''', 'run', 'no', '''
from utils import utils.assert.Assert

''' + '\n\n'.join([f'const func {t}() {{ {l} }}' for t,(_, l) in type_info.items()]) + '\n',
'\n    '.join([case(t, p) for t in op_info for p in [get_params(t)]]))

negative_tests = [template % (f'Check that {e} for arguments of type {t} is not const when `a` is not const.', 'compileonly', 'yes', f'''
func {f}() {{ {l} }}
''', expr(info, p)) for info in op_info for (p, op) in [(get_params(info), info[0])] for (arity, ty) in [(p['arity'], p['type'])]
  for (e, t, f, l) in [(rhs_expr('a', op, 'b', arity), type_info[ty][0], ty, type_info[ty][1])]]

counter = 1
def write_counted(contents : str):
  global counter
  with open(path.format(str(counter).zfill(2)), 'w') as file:
    file.write(contents)
    counter += 1

write_counted(positive_test)
for test in negative_tests:
  write_counted(test)
